#ifndef CRYPTSTREAM_
#define CRYPTSTREAM_

#define BLOCKSIZE 8

#include <stdio.h> // for size_t

class CryptStream {
public:
  CryptStream(const uint32_t key[4]);
  template<class T> void write(T data);
  template <class T, size_t N> void writearray(T(&data)[N]);
  void writebyte(uint8_t c);
  void finalize();
  uint8_t read();
  bool available();
  bool overflow();
private:
  uint8_t instream[BLOCKSIZE];
  uint8_t outstream[BLOCKSIZE];
  uint8_t instart;  // change type if BLOCKSIZE exceeds 255
  uint8_t outstart; // " "
  bool _available;
  bool _overflow;
  const uint32_t *_key;
};

template<class T> void CryptStream::write(T data) {
  /* Generic writing function, used to put a generic type of data in the input stream.
   * For each byte of data, the writebyte() function will be called.
   */
  for (size_t i=0; i<sizeof(data); i++) writebyte(((uint8_t*)&data)[i]);
};

template <class T, size_t N> void CryptStream::writearray(T(&data)[N]) {
  /* Array writing function, put an array in the input stream.
   * For each element of the array, the write() function will be called.
   */
  for (size_t i=0; i<N; i++) write(data[i]);
};

#endif
